
#include	"stm32f10x_Reg.h"
#include	"stm32f10x_Init.h"
#include 	<string.h>
#include	<stdio.h>
#include	"delay.h" 
#include	"transport.h"
#include	"ATOrg.h" 
#include	"string.h" 
#include	"stdlib.h" 
#include	"WIFIDevice.h"
#include	"MQTTConnect.h"
#include	"MQTTPacket.h"
#include 	<stdlib.h>
#include 	<cJSON.h>



#define _MQTT_TimeOutSET 2  //5ms计数2次为收到一个数据包
#define  MQRBufMaxLeg 256

static usint IRQRCnt=0;
static usint IRQRCntSV=0;
static uchar MQRBufSv[MQRBufMaxLeg];
static uchar MQRBuf[MQRBufMaxLeg];

static uchar MQTT_Order_TimeOutEN=0;
static uchar MQTT_TimeOutCNT=0;
static uchar MQTT_Datas_Finish=0;


void MQTT_TimeOut_Handler(void)   
{
	if(MQTT_Order_TimeOutEN)
	{
		if(++MQTT_TimeOutCNT>_MQTT_TimeOutSET)  //溢出
		{
			IRQRCntSV=IRQRCnt;
			IRQRCnt=0;
	
			MQTT_TimeOutCNT=0;	
			MQTT_Order_TimeOutEN=0;
			
			memcpy(MQRBufSv,MQRBuf,IRQRCntSV);
			MQTT_Datas_Finish=1; //完成了数据包的组合接收
			
			//USART1_TxDat(0xff);
			//UART1_Send_Length(MQRBufSv, IRQRCntSV);
			
		}
	}
}



/*
串口中断调用，组包靠时间，在溢出函数中组包
*/
void MQTT_RxIRQ(uchar Dat)
{
	MQRBuf[IRQRCnt++]=Dat;
	if(IRQRCnt>=MQRBufMaxLeg)
	{
		IRQRCnt=0;
	}
	
	//防止溢出
	MQTT_Order_TimeOutEN=1;
	MQTT_TimeOutCNT=0;
}



int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
	WSData(buf, buflen);
	return buflen;
}


int transport_getdata(unsigned char* buf, int count)
{
	if(MQTT_Datas_Finish==0)
	{
		return 0;
	}
	else
	{
		MQTT_Datas_Finish=0;

		/*
		if(IRQRCntSV<count) //收到的包没要求的长
		{
			return 0;
		}
		else
		*/
	
		{

			/*
			USART1_TxDat(0xff);
			UART1_Send_Length(MQRBufSv, IRQRCntSV);
			USART1_TxDat(0xAA);
			*/
			memcpy(buf,MQRBufSv,count);
			//printf("transport getdata:%d \n",count);
			return count;
		}
	}
}


uchar mqttTbuf[250];
static uchar sessionPresent=0, connack_rc=0;
static int req_qos =0;

uchar mqtt_connect(void)
{
    MQTTPacket_connectData data=MQTTPacket_connectData_initializer;
	
    int buflen = sizeof(mqttTbuf);
    int len=0;
	int rc = 0;
	
    data.clientID.cstring = "P2MDA"; //请修改其他客户名，防止其他用户使用冲突
    data.keepAliveInterval = 60; 	 //seconds
    data.cleansession = 1;
    data.username.cstring = "6amt6q1/P2MDA";
    data.password.cstring = "ifamvxidj7i5f5c5";
    data.MQTTVersion = 4;
	
	while(1)//重新发数据，等待连接
	{
		len = MQTTSerialize_connect((unsigned char *)mqttTbuf, buflen, &data);
		transport_sendPacketBuffer(mqttTbuf, len);
		printf("MQTT connect send len:%d \r\n", len);
    
		rc =-5;
		len=0;
		LoopTime(8000); //8秒钟内等待接收收据
		while(LoopSTA())
		{
			delay(300);
			/* wait for connack */
			if (MQTTPacket_read(mqttTbuf, buflen, transport_getdata) == CONNACK)
			{
				
				if (MQTTDeserialize_connack(&sessionPresent, &connack_rc, mqttTbuf, buflen) != 1 || connack_rc != 0)
				{
					rc =-2;
					printf("Unable to connect, return code %d\n", connack_rc);
				}
				else 
				{
					rc =0;
					printf("MQTT CONNECT!\n");
				}
			}
			else
			{
				rc =-1;
				printf("no connack...\n");
			}
			
			if(rc==0) 
			{
				return 0;
			}
		}
	}
}




static unsigned short submsgid=0;
static int subcount=0;
static int granted_qos=0;

//订阅函数
uchar mqtt_subscribe(char *pSubTopic)
{
    ulong buflen = sizeof(mqttTbuf);
    long msgid =1;
    int len=0;
    MQTTString topicString = MQTTString_initializer;
    topicString.cstring = pSubTopic;
	
	while(1)
	{
		len = MQTTSerialize_subscribe(mqttTbuf, buflen, 0, msgid, 1, &topicString, &req_qos);
		transport_sendPacketBuffer(mqttTbuf, len);

		LoopTime(4000); //4秒钟内等待接收收据
		while(LoopSTA())
		{
			delay(100);
			if (MQTTPacket_read(mqttTbuf, buflen, transport_getdata) == SUBACK) /* wait for suback */
			{
				if(MQTTDeserialize_suback(&submsgid, 1, &subcount, &granted_qos, mqttTbuf, buflen)==1)
				{
					
					printf("subcount:%d\r\n",subcount);
					printf("granted_qos:%d\r\n",granted_qos);
					printf("SUBSCRIBE Successfully\r\n");
					
					return 0;
				}
				else
				{
					printf("SUBSCRIBE failed\r\n");
				}

			}
			else
			{
				printf("no suback received!\r\n");
				
			}
		}
	}
	
}


//发布
void mqtt_publish(char *pPubTopic, char *pMessage)
{
	int len = 0;
    int buflen = sizeof(mqttTbuf);
    MQTTString topicString = MQTTString_initializer;
	
    char* payload = pMessage;
    int payloadlen = strlen(payload);

	topicString.cstring = pPubTopic;
	
    len=MQTTSerialize_publish(mqttTbuf, buflen,0,0,0,0, topicString, (uchar *)payload, payloadlen);
    transport_sendPacketBuffer(mqttTbuf, len);
}



/*
接收数据


*@param dup返回整数-MQTT dup标志
*@param qos返回整数-MQTT qos值
*@param retained返回整数-MQTT retained标志
*@param packetid返回整数-MQTT数据包标识符
*@param topicName返回MQTTString-发布中的MQTT主题
*@param payload返回字节缓冲区-MQTT publish payload
*@param payloadlen返回整数-MQTT有效负载的长度
*@param buf剩余长度字段确定的正确长度的原始缓冲区数据
*@param buflen所提供缓冲区中数据的字节长度


*@返回错误代码。1是成功

*/

static ulong PingNum=0;
int cJSON_Handle(void);
	


static uchar mqttRxbuf[200];
static unsigned char TOPIC[32];
static unsigned char payload[200];

static unsigned char MRdup=0;
static int MRqos=0;
static unsigned char MRretained=0;
static unsigned short MRmsgid=0;
static int MRpayloadlen_in=0;
static unsigned char *MRpayload_in;
static MQTTString MRreceivedTopic= MQTTString_initializer;
			

cJSON *json;
cJSON *object;

void mqtt_GetDating(void)
{
	ulong buflen = sizeof(mqttRxbuf);
  int rc=0;
	rc=MQTTPacket_read(mqttRxbuf,buflen,transport_getdata);
	
	
	
if ( rc == PUBLISH )
{
	if(MQTTDeserialize_publish(&MRdup, &MRqos, &MRretained, &MRmsgid, &MRreceivedTopic,&MRpayload_in, &MRpayloadlen_in, MQRBufSv, IRQRCntSV))
	{
		memcpy(TOPIC,MRreceivedTopic.lenstring.data, MRreceivedTopic.lenstring.len);
		memcpy(payload,MRpayload_in,MRpayloadlen_in);
		payload[MRpayloadlen_in]=0;//截止符
		TOPIC[MRreceivedTopic.lenstring.len]=0; //截止符
		
		//cJSON_Handle();  //JSON处理
		
		
		
	  /*
	  printf("MQTT Topic: %s\r\n", MRreceivedTopic.lenstring.data);
	  printf("MQTT DUP: %d\r\n", MRdup);
	  printf("MQTT Qos: %d\r\n", MRqos);
	  printf("MQTT retained: %d\r\n", MRretained);
	  printf("MQTT msgid: %d\r\n", MRmsgid);
	  */
		
		printf("MQTT[TOPIC:%s]:%s\r\n", TOPIC,payload); //打印收到的数据
		
		mqtt_publish("$baidu/iot/general/456",(char *)payload); //测试，，回传数据...

	}
}
else if(rc == PINGRESP) //ping消息
{
		++PingNum;
		//printf("Ping num=%d\r\n",PingNum);
}


}


ulong GetPingNum(void)
{
	return PingNum;
}
	
	


void mqtt_Ping_SendDat(void)
{
  ulong buflen = sizeof(mqttTbuf);
	int len = 0;
	
	len=MQTTSerialize_pingreq(mqttTbuf, buflen);
	transport_sendPacketBuffer(mqttTbuf, len);
}





int cJSON_Handle(void)
{
		printf("MQTT[TOPIC:%s]:%s\r\n", TOPIC,payload);
		
		//解析收到的文档 json----------------------------------
		//{"SID":"MainD01","TID":"WRB01","SvStart":6}
		json = cJSON_Parse( (const char *)payload );
		if(json == NULL)
		{
			printf("json fmt error:%s\n.", cJSON_GetErrorPtr());
			//mqtt_publish("WRobot/ACK", ACKjson0);
		}
		else
		{
			//---------------------------------------------------------
			object = cJSON_GetObjectItem(json, "GoOrigin");
			if(object!=NULL)
			{
				
				printf("printf->GoOrigin: %d\n", object->valueint);
			}

			cJSON_Delete(json);	
			}
		
			return 0;

}





static ulong TimeSV=0;
static ulong pingNum=0;
static uchar pingMark=0;
static uchar pingfailNum=0;


void mqttPig(void)
{

if( WaitTrue(9,10000) )
{
	mqtt_Ping_SendDat();
	//printf("Send ping:%d\r\n",++pingCnt);
	
	TimeSV=SysRunTime();
	pingMark=1;
}

if(pingMark)
{
	if(SysRunTime()>TimeSV+2000) //mqtt_Ping_SendDa
	{
		pingMark=0;
		if(GetPingNum()==pingNum)
		{
			printf("ping fail\r\n");
			++pingfailNum;
			if(pingfailNum>=3)
			{
				pingfailNum=0;
			
				printf("Ping 需要复位\r\n");
			}
		}
		else
		{
			pingNum=GetPingNum();
			pingfailNum=0;
			printf("ping ok:%d\r\n",pingNum);
		}
	}
}
}







